// 判断一个数字是不是质数
function isPrime(num) {
  for (var i = 2; i <= num / 2; i++) {
    if (num % i === 0) break
  }
  if (i <= num / 2) {
    return false
  } else {
    return true
  }
}

// 求任意个数字的和
function getAnd() {
  var sum = 0
  for (var i = 0; i < arguments.length; i++) {
    sum += arguments[i]
  }
  return sum
}

// 求一个数字的阶乘
function getJieCheng(num) {
  var sum = 1
  for (var i = 1; i <= num; i++) {
    sum *= i
  }
  return sum
}


// 转换成查询字符串     对象转成查询字符串格式
function queryStringify(obj) {
  var str = ''
  for (var k in obj) str += k + '=' + obj[k] + '&'
  return str.slice(0, -1)
}

// 查询字符串解析成对象
function parseQueryString(s, k) {
  var obj = {}
  s.split('&').forEach(function (item) {
    var t = item.split('=')
    obj[t[0]] = t[1]
  })
  return k ? obj[k] : obj
}

// 范围内的随机整数
function randomNum(a, b) {
  var max = Math.max(a, b)
  var min = Math.min(a, b)
  return Math.floor(Math.random() * (max - min + 1)) + min
}

// 一个随机颜色 rgb 形式
function randomColor() {
  var arr = []
  for (var i = 0; i < 3; i++) {
    arr.push(randomNum(0, 255))
  }
  return 'rgb(' + arr.join() + ')'
}

// 拼接六次16进制随机字符  随机颜色
// function randomColor(){
//   var color = "#";

//   // 算法 : 拼接六次16进制随机字符; 
//   // Math.round( Math.random() * 15 ).toString(16);
//   for(var i = 0 ; i < 6 ; i ++){
//         color += Math.round( Math.random() * 15 ).toString(16);
//   }

//   return color ; 
// }

// 获取时间差
function diffTime(curr, tar) {
  var diffMs = Math.ceil((tar.getTime() - curr.getTime()) / 1000)
  return {
    day: Math.floor(diffMs / (60 * 60 * 24)),
    hours: Math.floor(diffMs % (60 * 60 * 24) / (60 * 60)),
    minutes: Math.floor(diffMs % (60 * 60) / 60),
    seconds: diffMs % 60
  }
}


//    运动函数
function move(ele, target, fn) {
  let count = 0
  for (let k in target) {
    count++
    const timer = setInterval(() => {
      let current
      if (k === 'opacity') {
        current = window.getComputedStyle(ele)[k] * 100
      } else {
        current = parseInt(window.getComputedStyle(ele)[k])
      }
      let distance = (target[k] - current) / 10
      distance = distance > 0 ? Math.ceil(distance) : Math.floor(distance)
      if (current === target[k]) {
        clearInterval(timer)
        count--
        if (count === 0) fn()
      } else {
        if (k === 'opacity') {
          ele.style[k] = (current + distance) / 100
        } else {
          ele.style[k] = current + distance + 'px'
        }
      }
    }, 20)
  }
}


// ajax 封装
/*
  1. 对你传递的参数进行验证
    1-1. 验证你的 options 内 url 必填
      => 如果你没有 url, 不需要继续执行代码了
    1-2. 验证你的 options 内的 method 填写
      => 可以不传递, 只要你传递了, 必须是 GET 或者 POST
    1-3. 验证你的 options 内的 async 填写
      => 可以不传递, 只要你传递了, 必须是 true 或者 false
    1-4. 验证你的 options 内的 data 填写
      => 可以不传递, 只要你传递了, 必须是 字符串 类型
    1-5. 验证你的 options 内的 token 填写
      => 可以不传递, 只要你传递了, 必须是 字符串 类型
    1-6. 验证你的 options 内的 dataType 填写
      => 可以不传递, 只要你传递了, 必须是 'string' 或者 'json'
    1-7. 验证你的 options 内的 success 填写
      => 可以不传递, 只要你传递了, 必须是一个 function 类型
*/

function ajax(options = {}) {
  // options 就是你传递进来的所有对于本次请求的配置信息
  // console.log('你传递进来的数据 : ', options)

  // 1. 参数验证
  // 1-1. 验证 options.url
  if (!options.url) {
    // 表示 url 是 undefined 或者 null 或者 '' 或者 0
    // 手动抛出异常
    // 语法: throw new Error('报错信息')
    // 作用: 直接在控制台报错, 阻断程序的继续执行
    throw new Error('url 为必填选项, 请填写 ^_^')
  }

  // 1-2. 验证 options.method
  // 可以是 undefined, 可以是 'GET', 可以是 'POST'
  if (!(options.method === undefined || /^(get|post)$/i.test(options.method))) {
    // 代码能执行到这里, 说明你的 method 不是 undefined 不是 get 不是 post
    throw new Error('目前版本只接受 GET 和 POST 请求, 请期待更新 !! (#^.^#)')
  }

  // 1-3. 验证 options.async
  // 可以是 undefined, 可以是 布尔值
  if (!(options.async === undefined || typeof options.async === 'boolean')) {
    throw new Error('async 只能传递 布尔值, 请检查后操作')
  }

  // 1-4. 验证 options.data
  if (!(options.data === undefined || typeof options.data === 'string')) {
    throw new Error('data 需要传递一个 字符串 格式')
  }

  // 1-5. 验证 options.token
  if (!(options.token === undefined || typeof options.token === 'string')) {
    throw new Error('token 需要传递一个 字符串 格式')
  }

  // 1-6. 验证 options.dataType
  if (!(options.dataType === undefined || /^(string|json)$/i.test(options.dataType))) {
    throw new Error('dataType 只能传递 "string" 或者 "json"')
  }

  // 1-7. 验证 options.success
  if (!(options.success === undefined || typeof options.success === 'function')) {
    throw new Error('success 需要传递一个 function 类型的数据')
  }

  // 2. 设置一套默认值
  const _default = {
    // 代码能执行到这里, 说明 url 必须有值
    url: options.url,
    // 代码能来到这里, 说明 method 要么是 undefined, 要么是 GET, 要么是 POST
    method: options.method || 'GET',
    // 代码能来到这里, 说明 async 要么是 undefined, 要么是 true 要么是 false
    async: typeof options.async === 'boolean' ? options.async : true,
    // async: options.async ?? true
    // 代码能来到这里, 说明 data 要么是 undefined, 要么是 字符串
    data: options.data || '',
    // 代码能来到这里, 说明 token 要么是 undefined, 要么是 字符串
    token: options.token || '',
    // 代码能来到这里, 说明 dataType 要么是 undefined, 要么是 string 或者 json
    dataType: options.dataType || 'string',
    // 代码能来到这里, 说明 success 要么是 undefined, 要么是一个 函数
    success: options.success || function () {},
    error: options.error || function () {}
  }
  // 2-2. 判断一下, 如果是 GET 请求, 并且 data 有内容
  // 那么我们直接把 data 拼接到 url 的后面
  if (_default.method.toUpperCase() === 'GET' && _default.data) {
    // 代码能来到这里, 说明 是 GET 请求, 并且 data 有内容
    _default.url += '?' + _default.data
  }

  // 3. 按照 _default 内的内容发送请求

  // 3-1. 创建 ajax 对象
  const xhr = new XMLHttpRequest()

  // 3-2. 配置请求信息
  xhr.open(_default.method, _default.url, _default.async)

  // 3-3. 接受响应
  xhr.onload = function () {
    // 判断一下, 如果 dataType 是 'string' 那么我就不执行 JSON.parse()
    // 如果你的 dataType 是 'json' 那么我就执行一下 JSON.parse()
    const result = _default.dataType.toUpperCase() === 'JSON' ? JSON.parse(xhr.responseText) : xhr.responseText

    // 请求完成, 只要调用 success 函数就可以了
    _default.success(result)
  }

  // 3-4. 是否填写 token 作为请求头内的一个信息
  if (_default.token) xhr.setRequestHeader('authorization', _default.token)

  // 3-5. 如果是 POST 请求, 设置一下请求头的格式
  if (_default.method.toUpperCase() === 'POST') xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')

  // 3-6. 发送请求
  // 如果是 GET 请求, 直接书写 xhr.send()
  // 如果是 POST 请求你, 书写 xhr.send(参数)
  _default.method.toUpperCase() === 'POST' ? xhr.send(_default.data) : xhr.send()
}



// 对 ajax 进行 二次封装
function pAjax(options = {}) {
  const p = new Promise((resolve, reject) => {
    // 执行 ajax
    ajax({
      url: options.url,
      data: options.data,
      token: options.token,
      async: options.async,
      method: options.method,
      dataType: options.dataType,
      success: function (res) {
        resolve(res)
      }
    })
  })

  // 把我的 promise 对象返回出去
  return p
}

// 此时的全局变量 a 和 pAjax 内的 局部变量 p 是一模一样的东西
// const a = pAjax({ url: '/xxx', data: 'xxx', dataType: 'xxxx' })
// a.then(res => {})






/**
 * 设置 cookie
 * @param {String} key 你要设置的 cookie 的 key
 * @param {String} value 你要设置的 cookie 的 value
 * @param {Number} expires 你要设置的 cookie 的过期时间(单位是秒)
 * @returns 无
 */
 function setcookie(key, value, expires) {
  if (!expires) return document.cookie = `${ key }=${ value }`
  const time = new Date()
  time.setTime(time.getTime() - 1000 * 60 * 60 * 8 + 1000 * expires)
  document.cookie = `${ key }=${ value };expires=${ time }`
}


/**
 * 获取 cookie
 * @param {String} key 选填, 你要获取的 cookie 的 key
 * @returns { Object | String }
 */
function getcookie(key) {
  const obj = {}
  document.cookie.split('; ').forEach(item => {
    const t = item.split('=')
    obj[t[0]] = t[1]
  })
  return key ? obj[key] : obj
}


/**
 * 删除 cookie
 * @param {String} key 你要删除的 cookie 的 key
 */
function delcookie(key) {
  setcookie(key, '', -1)
}

